//#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "main_container.h"
#include "errors_warnings.h"
extern MainContainer * CompilerData;


/*
##SemanticsMethodStatementAssignment * ReadMSAssignment(SyntaxTreeNode * msAssignmentNode); (Gr_MethodStatement__Assignment, Gr_Assignment__VariableValue_opAssign_Expression_spSemiCol)
##SemanticsMethodStatementMethodCall * ReadMSMethodCall(SyntaxTreeNode * msMethodCallNode); (Gr_MethodStatement__MethodCall, Gr_MethodCall__NAME_spLPar_Parameters_spRPar_spSemiCol, Gr_MethodCall__VariableValue_spPer_NAME_spLPar_Parameters_spRPar_spSemiCol)
--->SemanticsMethodStatementCase * ReadMSCase(SyntaxTreeNode * msCaseNode); (Gr_SwitchCaseCases__SwitchCaseCase_SwitchCaseCases, Gr_SwitchCaseCase__case_spLPar_Expression_spRPar_spColon_SwitchCaseBlock, Gr_SwitchCaseDefault__default_spColon_SwitchCaseBlock)
--->SemanticsMethodStatementSwitchCase * ReadMSSwitchCase(SyntaxTreeNode * msSwitchCaseNode); (Gr_MethodStatement__SwitchCaseStatement, Gr_SwitchCaseStatement__switch_spLPar_Expression_spRPar_spLCBrac_SwitchCaseCases_SwitchCaseDefault_spRCBrac)
SemanticsMethodStatementBreak * ReadMSBreak(SyntaxTreeNode * msBreakNode); (Gr_MethodStatement__BreakStatement, Gr_BreakStatement__break_spSemiCol)
SemanticsMethodStatementContinue * ReadMSContinue(SyntaxTreeNode * msContinueNode); (Gr_MethodStatement__ContinueStatement, Gr_GotoStatement__goto_NAME_spSemiCol)
*/





//Gr_MethodStatement__Assignment
//Gr_Assignment__VariableValue_opAssign_Expression_spSemiCol
SemanticsMethodStatementAssignment * SemanticAnalyzer::ReadMSAssignment(SyntaxTreeNode * msAssignmentNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMSAssignment");
#endif

    SemanticsMethodStatementAssignment * msa;
	
	if (msAssignmentNode->Production == Gr_MethodStatement__Assignment)
	{
		// <method_statement> ~ <assignment>  {NAME}
		msa = ReadMSAssignment(msAssignmentNode->Nodes->GetData(0));
		
	}
	else if (msAssignmentNode->Production == Gr_Assignment__VariableValue_opAssign_Expression_spSemiCol)
	{
		// <assignment> ~ <variable_value> = <expression> ;  {NAME}
		msa = new SemanticsMethodStatementAssignment();
		
		//TODO : napraviti za LValue
		//SyntaxTreeNode * variableValueNode = msAssignmentNode->Nodes->GetData(0);
		//msa->LValue = ....

		SyntaxTreeNode * expressionNode = msAssignmentNode->Nodes->GetData(2);
		msa->RValue = GatherFromExpression(expressionNode);

		//type
		//msa->Type = MetStatAssignment;
		//label
						
				
	}
	else
	{
		// ERROR has been found
        // MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMSAssignment");
#endif

	return msa;
}


//Gr_MethodStatement__MethodCall
//Gr_MethodCall__NAME_spLPar_Arguments_spRPar_spSemiCol
//Gr_MethodCall__VariableValue_spPer_NAME_spLPar_Arguments_spRPar_spSemiCol
SemanticsMethodStatementMethodCall * SemanticAnalyzer::ReadMSMethodCall(SyntaxTreeNode * msMethodCallNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMSMethodCall");
#endif

	SemanticsMethodStatementMethodCall * msmc;
	
	
	if (msMethodCallNode->Production == Gr_MethodStatement__MethodCall)
	{
		// <method_statement> ~ <method_call>  {NAME}
		msmc = ReadMSMethodCall(msMethodCallNode->Nodes->GetData(0));
        
	}
	else if (msMethodCallNode->Production == Gr_MethodCall__NAME_spLPar_Arguments_spRPar_spSemiCol)
	{
		// <method_call> ~ NAME ( <arguments> ) ;  {NAME}

		SyntaxTreeNode * nameNode = msMethodCallNode->Nodes->GetData(0);
		msmc = new SemanticsMethodStatementMethodCall();
		msmc->Name= GatherFromNameNode(nameNode);
		
		SyntaxTreeNode * arguments = msMethodCallNode->Nodes->GetData(2);

		if (arguments->Production != Gr_Arguments__epsilon)
        {

            // add the initial parameter
            // <arguments> ~ <expression> <arguments_add>
            SyntaxTreeNode * expression = arguments->Nodes->GetData(0);
            msmc->Arguments->Add(GatherFromExpression(expression));

            // loop untill there are no more parameters
            // <arguments_add> ~ <argument_comma_add> <arguments_add>
            // <arguments_add> ~ ?
            // <argument_comma_add> ~ , <expression>
            SyntaxTreeNode * arguments_add = arguments->Nodes->GetData(1);
            while (arguments_add->Production != Gr_ArgumentsAdd__epsilon)
            {
                // <arguments_add> ~ <argument_comma_add> <arguments_add>
                // <argument_comma_add> ~ , <expression>
                SyntaxTreeNode * argument_comma_add = arguments_add->Nodes->GetData(0);
                expression = argument_comma_add->Nodes->GetData(1);
                
                msmc->Arguments->Add(GatherFromExpression(expression));


                arguments_add = arguments_add->Nodes->GetData(1);

				
            } 
			//msmc->Type = MetStatMethodCall;
			              
        }
        
	}
	else if (msMethodCallNode->Production == Gr_MethodCall__VariableValue_spPer_NAME_spLPar_Arguments_spRPar_spSemiCol)
	{
		// <method_call> ~ <variable_value> . NAME ( <arguments> ) ;  {NAME}
		
		SyntaxTreeNode * variableValue = msMethodCallNode->Nodes->GetData(1);	
		//
		//TODO napraviti za variablevalue
		//
		
		SyntaxTreeNode * arguments = msMethodCallNode->Nodes->GetData(4);

		if (arguments->Production != Gr_Arguments__epsilon)
        {

            // add the initial parameter
            // <arguments> ~ <expression> <arguments_add>
            SyntaxTreeNode * expression = arguments->Nodes->GetData(0);
			
			msmc = new SemanticsMethodStatementMethodCall();
            msmc->Arguments->Add(GatherFromExpression(expression));

            // loop untill there are no more parameters
            // <arguments_add> ~ <argument_comma_add> <arguments_add>
            // <arguments_add> ~ ?
            // <argument_comma_add> ~ , <expression>
            SyntaxTreeNode * arguments_add = arguments->Nodes->GetData(1);
            while (arguments_add->Production != Gr_ArgumentsAdd__epsilon)
            {
                // <arguments_add> ~ <argument_comma_add> <arguments_add>
                // <argument_comma_add> ~ , <expression>
                SyntaxTreeNode * argument_comma_add = arguments_add->Nodes->GetData(0);
                expression = argument_comma_add->Nodes->GetData(1);
                
                msmc->Arguments->Add(GatherFromExpression(expression));
			

                arguments_add = arguments_add->Nodes->GetData(1);
				
            } 
              
			//msmc->Type = MetStatMethodCall;
        }

	}
	else 
	{
		// ERROR has been found
        // MAKE LOGICAL RECOVERING
	}
	
#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMSMethodCall");
#endif
	
	return msmc;
}

//Gr_SwitchCaseCases__SwitchCaseCase_SwitchCaseCases
//Gr_SwitchCaseCase__case_spLPar_Expression_spRPar_spColon_SwitchCaseBlock 
//Gr_SwitchCaseDefault__default_spColon_SwitchCaseBlock
SemanticsMethodStatementCase * SemanticAnalyzer::ReadMSCase(SyntaxTreeNode * msCaseNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMSCase");
#endif
	SemanticsMethodStatementCase * msc = new SemanticsMethodStatementCase;
	
	// PROMJENA SINTAKSE!!!!!
	/*
	if (msCaseNode->Production == Gr_SwitchCaseCase__case_Expression_spColon_SwitchCaseBlock)
	{
		// <switch_case_case> ~ case <expression> : <switch_case_block>  {case}
		msc = new SemanticsMethodStatementCase();
		SyntaxTreeNode * expressionNode = msCaseNode->Nodes->GetData(2);
		msc->Expression = GatherFromExpression(expressionNode);

		// <switch_case_block> ~ <method_statement>  {NAME, if, while, for, do, switch, break, continue, return, goto, start, stop, derivation, trace, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream}
		// <switch_case_block> ~ ? {case, default, }}
		// <switch_case_block> ~ { <method_statements> }  {{}
		SyntaxTreeNode * switchCaseBlock = msCaseNode->Nodes->GetData(5);
		
		if (switchCaseBlock->Production == Gr_SwitchCaseBlock__MethodStatement)
		{
			SyntaxTreeNode * methodStatement = switchCaseBlock->Nodes->GetData(0);
			msc->CaseBody = (SemanticsMethodBody *) ReadMethodStatement(methodStatement);
			//type
			//msc->Type = MetStatSwitchCase;
		}
		else if (switchCaseBlock->Production == Gr_SwitchCaseBlock__spLCBrac_MethodStatements_spRCBrac)
		{
			SyntaxTreeNode * methodStaements = switchCaseBlock->Nodes->GetData(1);
			msc->CaseBody = ReadMethodBody(methodStaements);
			//type
			//msc->Type = MetStatSwitchCase;

		}
				
	}
	else if (msCaseNode->Production == Gr_SwitchCaseDefault__default_spColon_SwitchCaseBlock)
	{
		// <switch_case_default> ~ default : <switch_case_block>  {default}
		msc = new SemanticsMethodStatementCase();

		msc->Expression = NULL;

		SyntaxTreeNode * switchCaseBlock = msCaseNode->Nodes->GetData(2);
		
		if (switchCaseBlock->Production == Gr_SwitchCaseBlock__MethodStatement)
		{
			SyntaxTreeNode * methodStatement = switchCaseBlock->Nodes->GetData(0);
			msc->CaseBody = (SemanticsMethodBody *) ReadMethodStatement(methodStatement);
			//type
			//msc->Type = MetStatSwitchCase;
		}
		else if (switchCaseBlock->Production == Gr_SwitchCaseBlock__spLCBrac_MethodStatements_spRCBrac)
		{
			SyntaxTreeNode * methodStaements = switchCaseBlock->Nodes->GetData(1);
			msc->CaseBody = ReadMethodBody(methodStaements);
			//type
			//msc->Type = MetStatSwitchCase;

		}

	}
	
	
	else 
	{
		// ERROR has been found
        // MAKE LOGICAL RECOVERING
	}
	*/
#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMSCase");
#endif

	
	return msc;
}



// Gr_MethodStatement__SwitchCaseStatement,
// Gr_SwitchCaseStatement__switch_spLPar_Expression_spRPar_spLCBrac_SwitchCaseCases_SwitchCaseDefault_spRCBrac
SemanticsMethodStatementSwitchCase * SemanticAnalyzer::ReadMSSwitchCase(SyntaxTreeNode * msSwitchCaseNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMSSwitchCase");
#endif
	SemanticsMethodStatementSwitchCase * mssc;

	if (msSwitchCaseNode->Production == Gr_MethodStatement__SwitchCaseStatement)
	{
		// <method_statement> ~ <switch_case_statement>  {switch}
		mssc = ReadMSSwitchCase(msSwitchCaseNode->Nodes->GetData(0));

	}
	else if (msSwitchCaseNode->Production == Gr_SwitchCaseStatement__switch_spLPar_Expression_spRPar_spLCBrac_SwitchCaseCases_SwitchCaseDefault_spRCBrac)
	{
		// <switch_case_statement> ~ switch ( <expression> ) { <switch_case_cases> <switch_case_default> }  {switch}
		mssc = new SemanticsMethodStatementSwitchCase();

		SyntaxTreeNode * expressionNode = msSwitchCaseNode->Nodes->GetData(2);
		mssc->Expression = GatherFromExpression(expressionNode);



		// <switch_case_cases> ~ <switch_case_case> <switch_case_cases>  {case}
		// <switch_case_cases> ~ ? {default, }}
		SyntaxTreeNode * switchCaseCasesNode = msSwitchCaseNode->Nodes->GetData(5);

		while (switchCaseCasesNode->Production != Gr_SwitchCaseCases__epsilon)
		{
			SyntaxTreeNode * CaseNode = switchCaseCasesNode->Nodes->GetData(0);
			mssc->Cases->Add(ReadMSCase(CaseNode));

			switchCaseCasesNode = switchCaseCasesNode->Nodes->GetData(1);
		}
		

		SyntaxTreeNode * switchCaseDefaultNode = msSwitchCaseNode->Nodes->GetData(6);
        // <switch_case_default> ~ default : <switch_case_block>  {default}
		// <switch_case_default> ~ ? {}}

		if (switchCaseDefaultNode->Production != Gr_SwitchCaseDefault__epsilon)
		{
			mssc->Cases->Add(ReadMSCase(switchCaseDefaultNode));
		}

	}
	else 
	{
		// ERROR has been found
        // MAKE LOGICAL RECOVERING
	}

#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMSSwitchCase");
#endif

	return mssc;

}



//Gr_MethodStatement__BreakStatement
//Gr_BreakStatement__break_spSemiCol)
SemanticsMethodStatementBreak * SemanticAnalyzer::ReadMSBreak(SyntaxTreeNode * msBreakNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMSBreak");
#endif
    SemanticsMethodStatementBreak * msb;

	if (msBreakNode->Production == Gr_MethodStatement__BreakStatement)
	{
		// <method_statement> ~ <break_statement>  {break}
		msb = ReadMSBreak(msBreakNode->Nodes->GetData(0));

	}
	else if (msBreakNode->Production == Gr_BreakStatement__break_spSemiCol)
	{
		msb = new SemanticsMethodStatementBreak();
		// <break_statement> ~ break ;  {break}
		//msb->Type = MetStatBreak;

	}
	else
	{
		// ERROR has been found
        // MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMSBreak");
#endif


	return msb;

}


//Gr_MethodStatement__ContinueStatement
//Gr_GotoStatement__goto_NAME_spSemiCol
SemanticsMethodStatementContinue * SemanticAnalyzer::ReadMSContinue(SyntaxTreeNode * msContinueNode)
{
#ifdef TRACE
    CompilerData->LogTrace->ReportEntry("ReadMSContinue");
#endif
	SemanticsMethodStatementContinue * msc;
	if (msContinueNode->Production == Gr_MethodStatement__ContinueStatement)
	{
		// <method_statement> ~ <continue_statement>  {continue}
		msc = ReadMSContinue(msContinueNode->Nodes->GetData(0));
	}
	else if (msContinueNode->Production == Gr_ContinueStatement__continue_spSemiCol)
	{
		msc = new SemanticsMethodStatementContinue();
		//msc->Type = MetStatContinue;
	}
	else 
	{
		// ERROR has been found
        // MAKE LOGICAL RECOVERING
	}
	// <method_statement> ~ <continue_statement>  {continue}
	
	// <continue_statement> ~ continue ;  {continue}

	// <goto_statement> ~ goto NAME ;  {goto}
#ifdef TRACE
    CompilerData->LogTrace->ReportExit("ReadMSContinue");
#endif
	return msc;

}